import java.util.ArrayList;
import java.lang.Math;
/**Klasse zum konvertieren in Binärstrings
 * 
 * @author Björn Klemm, Gerd Ohlweiler, Anna Macjiewska
 *
 */
public class BitString {
	
	private int intField[];
	private String stringField;
	private String [] stringFieldList;
	
	public BitString(int intField[]) {
		this.intField = intField;
	}
	
	public BitString(String stringField) {
		this.stringField = stringField;
	}
	public BitString(String [] stringFieldList) {
		this.stringFieldList = stringFieldList;
	}
	
	/**
	 * Vorhandene Byte-Array in Boolean ArrayList schreiben
	 * @param source
	 * @return
	 */
	
	private ArrayList<Boolean> convertToArrayList(String [] source) {

		ArrayList <Boolean> results = new ArrayList();
		
		for(int i = 0;i<source.length;i++) {
			String line = source[i];
			for(int j=0;j<128;j++) {
				if(line.charAt(j) =='1') {
					results.add(true);
				} else {
					results.add(false);
				}
				
			}
		}

		return results;

	}
	
	/**
	 * Ergebnisse der Umwandlung in Byte-String in Array schreiben
	 * @param binNumber
	 * @param returnField
	 * @return
	 */

	private String [] writeBinToResult(String binNumber, String []returnField) {

		for(int i=0;i<returnField.length;i++) {
			if(returnField[i] != null) {
				if(returnField[i].length()<128) {
					returnField[i] = returnField[i]+""+binNumber;
					break;
				} 
			} else {
				returnField[i] = binNumber;
				break;
			}
		}
		return returnField;
		
	}
	
	/**
	 * Beginn der Zahl mit X-Stellen von 0 auffuellen
	 * @param bit
	 * @param value
	 * @return
	 */
	
	private String fillForXBit(int bit, String value) {
		String returnValue = "";
		int i = 0;
		int toFill = bit - value.length();
		while(i < toFill) {
			returnValue = returnValue+"0";
			i++;
		}
		returnValue = returnValue+""+value;
		return returnValue;
	}
	
	/**
	 * Integer Value in Byte-String umwandeln
	 * @param value
	 * @return
	 */
	
	private String convertIntToByte(int value) {
		String result = "";

		while (value>0)
		{
			result=value%2+result;
			value=value/2;
		}
		return result;
	}
	
	/**
	 * Byte-String in Integer-Wert umwandeln
	 * @param byteString
	 * @return
	 */
	
	private int convertByteToInt(String byteString) {
			
			int index = byteString.length()-1;
			double result = 0;
			int head = 0;
			while(index>=0) {
				char position = byteString.charAt(index);
				if(position == '1') {
					result = (result + java.lang.Math.pow(2,head));
				}
				head++;
				index--;
			}
	   		return (int)result;
		
	}
	
	/**
	 * Array mit Integer-Werten in String-Array mit Byte-Werten umwandeln. Je Feld stehen 128 Zeichen zur Verfuegung.
	 * @param values
	 * @return
	 */
	
	private String [] convertIntArrayToBitArray(int values []) {
		int size = values.length*32/128;
		if(size == 0)
			size = 1;
		String returnField[] = new String [size+1];
	
		for(int i=0;i<values.length;i++) {
			String binNumber = convertIntToByte(values[i]);
			binNumber = fillForXBit(32,binNumber);
			returnField = writeBinToResult(binNumber, returnField);
		}


		return returnField;
	}
	
	/**
	 * Laenge des Arrays errechnen
	 * @param bitArray
	 * @param bit
	 * @return
	 */
	
	private int getBitArrayLength(String [] bitArray, int bit) {
		
		int length = (bitArray.length-1)*128/bit;
		int lastLine = bitArray[bitArray.length-1].length() / bit;
		length = length + lastLine;	
		return length;
	}
	

	/**
	 * Byte-Array in Int-Array konvertieren
	 * @param bitArray
	 * @return
	 */
	
	private int [] convertBitArrayToIntArray(String [] bitArray) {
		int [] targetArray = new int [getBitArrayLength(bitArray,32)];
		int counter = 0;
		for(int i=0;i<bitArray.length-1;i++) {
			String line = bitArray[i];
			targetArray[counter] = convertByteToInt(line.substring(0, 32));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(32, 64));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(64, 96));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(96, 128));
			counter++;
		}
		
		//Last Line:
		String line = bitArray[bitArray.length-1];
		int lineLength = line.length();
		
		if(lineLength == 32) {
			targetArray[counter] = convertByteToInt(line.substring(0, 32));
			counter++;
		}
		else if(lineLength == 64) {
			targetArray[counter] = convertByteToInt(line.substring(0, 32));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(32, 64));
			counter++;
		}
		else if(lineLength == 96) {
			targetArray[counter] = convertByteToInt(line.substring(0, 32));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(32, 64));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(64, 96));
			counter++;
		}
		else if(lineLength == 128) {
			
			targetArray[counter] = convertByteToInt(line.substring(0, 32));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(32, 64));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(64, 96));
			counter++;
			targetArray[counter] = convertByteToInt(line.substring(96, 128));
			counter++;
		}

		return targetArray;
	}
	
	/**
	 * Character in Byte-Array umwandeln.
	 * @param c
	 * @return
	 */
	
	private String convertCharToByte(char c) {
		int digit = c;
		String binValue = convertIntToByte(digit);
		binValue = fillForXBit(8,binValue);
		return binValue;
		
	}
	
	/**
	 * Byte-String in Character umwandeln
	 * @param binValue
	 * @return
	 */
	
	private char convertByteToChar(String binValue) {
		int code = convertByteToInt(binValue);
		char c = (char) code;
		return c;
	}

	/**
	 * String-Array in Byte-Array umwandeln
	 * @param stringFieldList
	 * @return
	 */

	private String[] convertStringArrayToByte(String[] stringFieldList) {
		int signs = 0;
		//laenge berechnen
		for(int i=0;i<stringFieldList.length;i++) {
			signs = signs + stringFieldList[i].length();
		}
		signs = signs * 8;
		
		String returnField[] = new String [signs/128+1];
		for(int i=0;i<stringFieldList.length;i++) {
			String line = stringFieldList[i];
			char[] lineChars = line.toCharArray();
			for(int j=0;j<lineChars.length;j++) {
				
				String binString = convertCharToByte(lineChars[j]);
				binString = fillForXBit(8,binString);
				System.out.println(lineChars[j]+"->"+binString);
				returnField = writeBinToResult(binString, returnField);
			}
			
		}
		
		for(int j=0;j<returnField.length;j++) {
			System.out.println(returnField[j]);
		}
		
		return returnField;
	}
	
	/**
	 * Byte-Array in String-Array konvertieren
	 * @param stringFieldList
	 * @return
	 */
	
	private String[] convertByteArrayToString(String[] stringFieldList) {
		//Laenge des Ziel-Arrays festlegen
		int length = 1;
		int position = 0;
		int finalPosition = position + 15;
		for(int i=0;i<stringFieldList.length;i++)  {
			while(finalPosition < stringFieldList[i].length()) {
				String value = stringFieldList[i].substring(position, position+16);
				if(value.equals("0000110100001010")) {
					System.out.println("umbruch");
					length++;
				}
				position = position + 16;
				finalPosition = finalPosition + 16;
			}
	
		}
		String [] targetStrings = new String [length];
		int j=0;
		position = 0;
		finalPosition = position + 8;
		String row = "";
		//Werte umcodieren und in das Target-Array kopieren
		for(int i=0;i<stringFieldList.length;i++) {
			while(finalPosition < stringFieldList[i].length()) {
				String value = stringFieldList[i].substring(position, position + 8);
				char c = convertByteToChar(value);
				row = row +""+c;
				System.out.println(c+" -> "+row);
				System.out.println(row);
				position = position + 8;
				finalPosition = finalPosition + 8;
			}
			targetStrings[i] = row;
			row="";
			
		}
		
		
		return targetStrings;
	}

	
	public String[]getString() {
		return convertByteArrayToString(stringFieldList);
	}

	public String[] getBinaryString() {
		return convertStringArrayToByte(stringFieldList);
	}
	
	public int [] getIntegerArray() {
		return convertBitArrayToIntArray(stringFieldList);
	}


}
